<template>
    <n-drawer
        v-model:show="showModel"
        :width="1000"
        :height="500"
        placement="right"
    >
        <n-drawer-content title="设置字段" closable :native-scrollbar="false">
            <n-flex justify="space-between" style="margin-bottom: 10px">
                <n-space>
                    <n-button
                        type="error"
                        secondary
                        v-if="checkedRowKeys.length"
                        @click="onDeleteBatch"
                        >删除</n-button
                    >
                    <n-button
                        type="primary"
                        secondary
                        v-if="checkedRowKeys.length"
                        @click="onCopy"
                    >
                        {{ copied ? 'Copied!' : '复制' }}

                        <template #icon v-if="copied">
                            <n-icon>
                                <CheckCircleOutlineRound />
                            </n-icon>
                        </template>
                    </n-button>

                    <n-button
                        v-if="canPasteList"
                        type="warning"
                        secondary
                        @click="onPaste"
                        >粘贴</n-button
                    >
                </n-space>

                <n-space>
                    <n-button
                        type="info"
                        @click="onEdit()"
                        :disabled="submiting || typeof editIndex === 'number'"
                        >添加字段</n-button
                    >

                    <n-button
                        type="primary"
                        @click="onSubmit"
                        :disabled="typeof editIndex === 'number'"
                        :loading="submiting"
                        >保存</n-button
                    >
                </n-space>
            </n-flex>

            <n-form
                ref="formRef"
                :model="formState"
                :rules="formRules"
                label-placement="left"
                label-width="auto"
            >
                <n-data-table
                    :loading="loading"
                    :columns="columns"
                    :data="list"
                    :bordered="false"
                    v-model:checked-row-keys="checkedRowKeys"
                    :row-key="(data) => data.field"
                    size="small"
                />
            </n-form>
        </n-drawer-content>
    </n-drawer>

    <SetRules v-model:show="showRules" v-model:model-value="formState.rule" />
</template>

<script setup lang="ts">
import { coreFieldList, coreFieldSaveBatch } from '@/apis/core/field'
import { ICoreField } from '@/types/core/field'
import {
    NForm,
    NDrawer,
    NDrawerContent,
    NDataTable,
    createDiscreteApi,
    NFlex,
    NSpace,
    NButton,
    NInput,
    NFormItem,
    FormRules,
    FormInst,
    NIcon,
    DataTableColumn
} from 'naive-ui'
import { computed, h, onMounted, onUnmounted, ref, watch } from 'vue'
import {
    EditOffTwotone,
    DeleteOutlineRound,
    CheckCircleOutlineRound,
    RemoveCircleOutlineOutlined,
    AnimationSharp
} from '@vicons/material'
import useState from '@/hooks/useState'
import { COPIED_FIELD_LIST } from '@/config/constant'
import SetRules from './SetRules.vue'

const emits = defineEmits(['update:show'])

const props = defineProps({
    show: {
        type: Boolean,
        default: () => false
    },
    hashId: {
        type: Number
    }
})

const showModel = computed({
    get: () => props.show,
    set: (val) => emits('update:show', val)
})

const { message } = createDiscreteApi(['message'])
const loading = ref(false)
const list = ref<(ICoreField & { isNew?: boolean })[]>([])
const columns: DataTableColumn<ICoreField>[] = [
    {
        type: 'selection'
    },
    {
        title: '名称',
        key: 'name',
        width: 150,
        render(row, index) {
            if (index === editIndex.value) {
                return h(
                    NFormItem,
                    {
                        path: 'name'
                    },
                    {
                        default: () =>
                            h(NInput, {
                                value: formState.value.name,
                                onUpdateValue(v) {
                                    formState.value.name = v
                                },
                                clearable: true
                            })
                    }
                )
            }

            return row.name
        }
    },
    {
        title: '字段',
        key: 'field',
        width: 150,
        render(row, index) {
            if (index === editIndex.value) {
                return h(
                    NFormItem,
                    {
                        path: 'field'
                    },
                    {
                        default: () =>
                            h(NInput, {
                                value: formState.value.field,
                                onUpdateValue(v) {
                                    formState.value.field = v
                                },
                                clearable: true
                            })
                    }
                )
            }
            return row.field
        }
    },
    {
        title: '验证规则',
        key: 'rule',
        width: 240,
        render(row, index) {
            if (index === editIndex.value) {
                return h(
                    NFormItem,
                    {
                        path: 'rule'
                    },
                    {
                        default: () =>
                            h(
                                NInput,
                                {
                                    value: formState.value.rule,
                                    onUpdateValue(v) {
                                        formState.value.rule = v
                                    },
                                    clearable: true,
                                    type: 'textarea',
                                    autosize: true
                                },
                                {
                                    suffix: () =>
                                        h(
                                            NButton,
                                            {
                                                size: 'tiny',
                                                bordered: false,
                                                type: 'info',
                                                secondary: true,
                                                circle: true,
                                                onClick: () => pickRules()
                                            },
                                            {
                                                default: () =>
                                                    h(
                                                        NIcon,
                                                        {},
                                                        {
                                                            default: () =>
                                                                h(
                                                                    AnimationSharp
                                                                )
                                                        }
                                                    )
                                            }
                                        )
                                }
                            )
                    }
                )
            }
            return row.rule
        }
    },
    {
        title: '备注',
        key: 'remark',
        render(row, index) {
            if (index === editIndex.value) {
                return h(
                    NFormItem,
                    {
                        path: 'remark'
                    },
                    {
                        default: () =>
                            h(NInput, {
                                type: 'textarea',
                                autosize: true,
                                value: formState.value.remark,
                                onUpdateValue(v) {
                                    formState.value.remark = v
                                },
                                clearable: true
                            })
                    }
                )
            }
            return row.remark
        }
    },
    {
        title: '操作',
        key: 'actions',
        width: 140,
        render(rowData, rowIndex) {
            if (rowIndex === editIndex.value) {
                return h(
                    NSpace,
                    {
                        style: {
                            height: '35.4px',
                            alignItems: 'center'
                        }
                    },
                    {
                        default: () => [
                            h(
                                NButton,
                                {
                                    size: 'tiny',
                                    type: 'success',
                                    onClick() {
                                        onSave()
                                    }
                                },
                                {
                                    default: () => '保存',
                                    icon: () => h(CheckCircleOutlineRound)
                                }
                            ),
                            h(
                                NButton,
                                {
                                    size: 'tiny',
                                    type: 'error',
                                    onClick: () => onCancel()
                                },
                                {
                                    icon: () => h(RemoveCircleOutlineOutlined),
                                    default: () => '取消'
                                }
                            )
                        ]
                    }
                )
            }

            return h(
                NSpace,
                {},
                {
                    default: () => [
                        h(
                            NButton,
                            {
                                size: 'tiny',
                                type: 'error',
                                secondary: true,
                                disabled: typeof editIndex.value === 'number',
                                onClick: () => onDelete(rowIndex)
                            },
                            {
                                icon: () => h(DeleteOutlineRound),
                                default: () => '删除'
                            }
                        ),
                        h(
                            NButton,
                            {
                                size: 'tiny',
                                type: 'info',
                                secondary: true,
                                disabled: typeof editIndex.value === 'number',
                                onClick: () => onEdit(rowData, rowIndex)
                            },
                            {
                                icon: () => h(EditOffTwotone),
                                default: () => '编辑'
                            }
                        )
                    ]
                }
            )
        }
    }
]
function getList() {
    coreFieldList({
        hash_id: props.hashId!
    })
        .then((res) => {
            list.value = res
        })
        .catch((e: Error) => message.error(e.message))
        .finally(() => {
            loading.value = false
        })
}

onMounted(() => {
    if (props.show) getList()
})
const stopWatch1 = watch(
    () => props.show,
    (val) => {
        if (val) {
            getList()
            getCanPasteList()
            checkedRowKeys.value = []
        }
    }
)
onUnmounted(() => {
    if (stopWatch1) stopWatch1()
})

/**
 * 多选
 */
const checkedRowKeys = ref<string[]>([])

/**
 * 复制
 */
const { state: copied, setState: setCopied } = useState()
function onCopy() {
    if (copied.value) return
    const checkedList = list.value.filter((item) =>
        checkedRowKeys.value.includes(item.field)
    )

    setCopied(true)
    sessionStorage.setItem(COPIED_FIELD_LIST, JSON.stringify(checkedList))
    getCanPasteList()
    setTimeout(() => {
        setCopied(false)
    }, 1000)
}
const canPasteList = ref<ICoreField[] | null>(null)
function getCanPasteList() {
    const localList = sessionStorage.getItem(COPIED_FIELD_LIST)
    if (localList) {
        canPasteList.value = []
        ;(JSON.parse(localList) as ICoreField[]).forEach((item) => {
            canPasteList.value?.push({
                ...item,
                hash_id: props.hashId!
            })
        })
    } else {
        canPasteList.value = null
    }
}
function onPaste() {
    // 融合数据
    if (canPasteList.value) {
        list.value = [...list.value, ...canPasteList.value]
    }

    // 清空
    sessionStorage.removeItem(COPIED_FIELD_LIST)
    getCanPasteList()
}

/**
 * 删除
 */
function onDelete(index: number) {
    list.value.splice(index, 1)
}
function onDeleteBatch() {
    const removeIndexs: number[] = []
    checkedRowKeys.value.forEach((field) => {
        const i = list.value.findIndex((item) => item.field === field)
        removeIndexs.push(i)
    })

    checkedRowKeys.value.length = 0

    // 倒序遍历索引数组
    removeIndexs
        .sort((a, b) => b - a)
        .forEach((index) => {
            list.value.splice(index, 1)
        })
}

/**
 * 添加
 */
const formRef = ref<FormInst | null>(null)
const formRules: FormRules = {
    name: [
        { required: true, message: '名称不能为空', trigger: ['input', 'blur'] },
        {
            min: 2,
            max: 20,
            message: '名称长度在2~20个字符',
            trigger: ['input', 'blur']
        }
    ],
    field: [
        { required: true, message: '字段不能为空', trigger: ['input', 'blur'] },
        {
            min: 2,
            max: 20,
            message: '字段长度在2~20个字符',
            trigger: ['input', 'blur']
        },
        {
            trigger: ['input', 'blur'],
            validator(_rule, value) {
                if (!/^[a-zA-Z0-9_-]+$/.test(value)) {
                    return new Error('只能包含英文、数字、下划线_和中划线-')
                }

                if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(value)) {
                    return new Error('只能以英文开头')
                }

                return true
            }
        }
    ]
}
const defaultFormState: ICoreField & {
    isNew: boolean
} = {
    hash_id: props.hashId!,
    name: '',
    field: '',
    rule: '',
    remark: '',

    isNew: true
}
const editIndex = ref<number | null>(null)
const formState = ref<
    ICoreField & {
        isNew: boolean
    }
>({ ...defaultFormState })
function onEdit(record?: ICoreField, index?: number) {
    if (typeof index === 'undefined') {
        list.value.push({ ...defaultFormState })
        editIndex.value = list.value.length - 1
        formState.value = { ...defaultFormState, hash_id: props.hashId! }
    } else {
        editIndex.value = index
        formState.value = { ...record!, isNew: false }
    }
}
function onSave() {
    formRef.value
        ?.validate()
        .then(() => {
            list.value[editIndex.value!] = {
                ...formState.value,
                isNew: false
            }
            editIndex.value = null
        })
        .catch((e: Error) => {
            if (e?.message) {
                message.error(e.message)
            }
        })
}
function onCancel() {
    if (formState.value.isNew) {
        list.value.splice(editIndex.value!, 1)
    }
    editIndex.value = null
}

const { state: submiting, setState: setSubmiting } = useState()
function onSubmit() {
    setSubmiting(true)
    coreFieldSaveBatch({
        hash_id: props.hashId!,
        list: list.value
    })
        .then(() => {
            showModel.value = false
            message.success('保存成功')
        })
        .catch((e: Error) => message.error(e.message))
        .finally(() => setSubmiting(false))
}

/**
 * 选择规则
 */
const { state: showRules, setState: setShowRules } = useState()
function pickRules() {
    setShowRules(true)
}
</script>

<style lang="less" scoped>
:deep(.n-data-table) {
    .n-data-table-tr {
        vertical-align: top !important;
    }

    .n-data-table-td--selection,
    .n-data-table-th--selection {
        vertical-align: middle !important;
    }
}
:deep(.n-form) {
    .n-form-item-feedback-wrapper {
        min-height: auto;
    }
}
</style>
